/*
 * FLRFile.cpp
 *
 *  Created on: Sep 19, 2011
 *      Author: kimi
 */

#include "FLRFile.h"

// getByID
bool FLRFile::getRecordByID(unsigned long recordID, char** record) {

	if (recordID >= recordCount) {
		return false;
	}
	if ((*record) != NULL) {
		return false;
	}

	_file.seekg(sizeof(unsigned long)+recordID*recordSize,ios::beg);

	(*record) = new char[recordSize];

	if ((*record) == NULL) {
		return false;
	}

	_file.read((*record),recordSize);

	return true;
}

//unsigned long add(reg) - agrega al final . devuelve record ID
bool FLRFile::addRecord(unsigned long *recordID, char* record) {
	if (record == NULL)
		return false;

	// get free space
	bool fspace = spaceMgr->get(recordID);

	if (fspace != false) {
		_file.seekp(sizeof(unsigned long)+(*recordID)*recordSize,ios::beg);
	}
	else {
		*recordID = recordCount;
		recordCount++;

		// actualiza Record Count
		_file.seekp(0,ios::beg);
		_file.write(reinterpret_cast<char*>(&recordCount), sizeof(unsigned long));

		// write block into file
		_file.seekp(0,ios::end);

	}

	_file.write(record,recordSize);
	_file.flush();

	return true;
}

bool FLRFile::updateRecord(unsigned long recordID, char* record) {

	if (recordID >= recordCount) {
		return false;
	}
	if (record == NULL) {
		return false;
	}
	if (spaceMgr->has(recordID)) {
		return false;
	}

	_file.seekp(sizeof(unsigned long)+recordID*recordSize,ios::beg);

	_file.write(record,recordSize);
	_file.flush();

	return true;
}

bool FLRFile::deleteRecord(unsigned long recordID) {
	if (spaceMgr->has(recordID) == false) {
		return spaceMgr->add(recordID);
	}

	return true;
}

FLRFile::FLRFile(string xfilePath, unsigned long xRegSize) {
	// open file
	recordSize = xRegSize;
	recordCount = 0;

	filePath = xfilePath;
	_file.open(filePath.c_str(),ios::out | ios::in | ios::binary);

	if (!_file.is_open())
		_file.open(filePath.c_str(), ios::in | ios::out | ios::trunc | ios::binary);

	//TODO: Mejorar usando el logger.
	if (!_file.is_open())
		throw ios_base::failure("cannot create file at \"" + filePath + "\".");


	_file.seekg(0,ios::end);
	if (_file.tellg() >= sizeof(unsigned long)) {
		_file.seekg(0,ios::beg);
		_file.read(reinterpret_cast<char*>(&recordCount), sizeof(unsigned long));
	}
	else {
		_file.seekp(0,ios::beg);
		_file.write(reinterpret_cast<char*>(&recordCount), sizeof(unsigned long));
		_file.flush();
	}

	spaceMgr = new EmptySpaceMgr(filePath + ".freelist");
}

bool FLRFile::truncateFile(unsigned long xRecordCount) {
	recordCount = xRecordCount;
	_file.seekp(0,ios::beg);
	_file.write(reinterpret_cast<char*>(&recordCount), sizeof(unsigned long));
	_file.flush();

	return true;
}

FLRFile::~FLRFile() {
	_file.flush();
	_file.close();
	delete spaceMgr;
}

void FLRFile::purge() {
	truncateFile(0);
	spaceMgr->deleteAll();
}

unsigned long FLRFile::getRecordCount() {
	return recordCount;
}

unsigned long FLRFile::getRecordSize() {
	return recordSize;
}
